package com.foreveross.crawl.adapter;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.foreveross.crawl.common.util.DateUtil;
import com.foreveross.crawl.common.util.RegHtmlUtil;
import com.foreveross.crawl.common.util.StringUtils;
import com.foreveross.crawl.domain.airfreight.AbstractPlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.TransitEntity;
import com.foreveross.crawl.domain.airfreight.doub.CabinRelationEntity;
import com.foreveross.crawl.domain.airfreight.doub.DoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnDoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnTransitEntity;
import com.foreveross.crawl.domain.airfreight.single.SinglePlaneInfoEntity;
import com.foreveross.taskservice.common.bean.TaskModel;

public class PlaneInfoEntityBuilder {

	protected static Logger logger = LoggerFactory.getLogger(PlaneInfoEntityBuilder.class);

	/**
	 * 因为加多了税价合计价几个参数，所以使用加多参数的buildPlaneInfo方法
	 * 
	 * @deprecated
	 * @param task
	 * @param carrierKey
	 * @param carrierName
	 * @param carrierFullName
	 * @param startTime
	 * @param endTime
	 * @param flightNo
	 * @param totalLowestPrice
	 * @param agentName
	 * @param totalHighestPrice
	 * @param type
	 * @param clzz
	 * @return
	 * @throws Exception
	 */
	public static <T extends AbstractPlaneInfoEntity> T buildPlaneInfo(TaskModel task, String carrierKey, String carrierName, String carrierFullName, String startTime, String endTime, String flightNo, String totalLowestPrice, String agentName,
			String totalHighestPrice, String type, Class<T> clzz) throws Exception {
		return buildPlaneInfo(task, carrierKey, carrierName, carrierFullName, startTime, endTime, flightNo, totalLowestPrice, agentName, totalHighestPrice, type, null, null, null, null, clzz);
	}

	/**
	 * 传递最基本的参数和class构造单程、往返去程、往返回程实体
	 * 
	 * @param task
	 * @param carrierKey
	 * @param carrierName
	 * @param carrierFullName
	 * @param startTime
	 * @param endTime
	 * @param flightNo
	 * @param totalLowestPrice
	 * @param agentName
	 * @param totalHighestPrice
	 * @param type
	 * @param sumLowestPrice
	 * @param totalLowestTaxesPrice
	 * @param clzz
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T extends AbstractPlaneInfoEntity> T buildPlaneInfo(TaskModel task, String carrierKey, String carrierName, String carrierFullName, String startTime, String endTime, String flightNo, String totalLowestPrice, String agentName,
			String totalHighestPrice, String type, String sumLowestPrice, String sumHighestPrice, String totalLowestTaxesPrice, String totalHighestTaxesPrice, Class<T> clzz) throws Exception {
		AbstractPlaneInfoEntity entity = clzz.newInstance();
		entity.setSumLowestPrice(StringUtils.isNotBlank(sumLowestPrice) && NumberUtils.isNumber(sumLowestPrice) ? Double.valueOf(sumLowestPrice.trim()) : null);
		entity.setSumHighestPrice(StringUtils.isNotBlank(sumHighestPrice) && NumberUtils.isNumber(sumHighestPrice) ? Double.valueOf(sumHighestPrice.trim()) : null);
		entity.setTotalLowestTaxesPrice(StringUtils.isNotBlank(totalLowestTaxesPrice) && NumberUtils.isNumber(totalLowestTaxesPrice) ? Double.valueOf(totalLowestTaxesPrice.trim()) : null);
		entity.setTotalHighestTaxesPrice(StringUtils.isNotBlank(totalHighestTaxesPrice) && NumberUtils.isNumber(totalHighestTaxesPrice) ? Double.valueOf(totalHighestTaxesPrice.trim()) : null);
		setPlaneInfo(task, carrierKey, carrierName, carrierFullName, startTime, endTime, flightNo, totalLowestPrice, agentName, totalHighestPrice, type, entity);
		if (clzz.equals(ReturnDoublePlaneInfoEntity.class)) {
			setPlaneInfo(task, entity, false);
			// 去程设置日期
			entity.setStartTime(CrawlAdapterFactory.getFlightTime(task.getReturnGrabDate(), startTime));
			entity.setEndTime(CrawlAdapterFactory.getFlightTime(task.getReturnGrabDate(), endTime));
		} else {
			setPlaneInfo(task, entity, true);
			// 去程设置日期
			entity.setStartTime(CrawlAdapterFactory.getFlightTime(task.getFlightDate(), startTime));
			entity.setEndTime(CrawlAdapterFactory.getFlightTime(task.getFlightDate(), endTime));
		}
		return (T) entity;
	}

	/**
	 * 因为加多了税价合计价几个参数，所以使用加多参数的buildCabinInfo方法
	 * 
	 * @deprecated
	 * @param cabinType
	 * @param subCabinName
	 * @param productName
	 * @param price
	 * @param originalPrice
	 * @param tuigaiqian
	 * @param lastSeatInfo
	 * @param clzz
	 * @return
	 * @throws Exception
	 */
	public static <T> T buildCabinInfo(String cabinType, String subCabinName, String productName, String price, String originalPrice, String tuigaiqian, String lastSeatInfo, Class<T> clzz) throws Exception {
		return buildCabinInfo(cabinType, subCabinName, productName, null, price, originalPrice, tuigaiqian, lastSeatInfo, clzz);
	}

	/**
	 * 构建一个仓位实体
	 * 
	 * @param cabinType
	 * @param subCabinName
	 * @param productName
	 * @param price
	 * @param originalPrice
	 * @param clzz
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> T buildCabinInfo(String cabinType, String subCabinName, String productName, String taxesPrice, String price, String originalPrice, String tuigaiqian, String lastSeatInfo, Class<T> clzz) throws Exception {
		Double p = StringUtils.isNotBlank(price) && NumberUtils.isNumber(price) ? Double.valueOf(price.trim()) : null;
		Double op = StringUtils.isNotBlank(originalPrice) && NumberUtils.isNumber(originalPrice) ? Double.valueOf(originalPrice.trim()) : null;
		Double tax = StringUtils.isNotBlank(taxesPrice) && NumberUtils.isNumber(taxesPrice) ? Double.valueOf(taxesPrice.trim()) : null;
		if (com.foreveross.crawl.domain.airfreight.CabinEntity.class.equals(clzz)) {
			com.foreveross.crawl.domain.airfreight.CabinEntity entity = new com.foreveross.crawl.domain.airfreight.CabinEntity();
			entity.setCabinType(cabinType);
			entity.setSubCabinName(subCabinName);
			entity.setProductName(productName);
			entity.setPrice(p);
			entity.setTaxesPrice(tax);
			if (op != null) entity.setOriginalPrice(op);
			else entity.setOriginalPrice(tax == null ? null : p + tax);
			entity.setTuigaiqian(tuigaiqian);
			entity.setLastSeatInfo(lastSeatInfo);
			return (T) entity;
		} else if (com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity.class.equals(clzz)) {
			com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity entity = new com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity();
			entity.setCabinType(cabinType);
			entity.setSubCabinName(subCabinName);
			entity.setProductName(productName);
			entity.setPrice(p);
			entity.setTaxesPrice(tax);
			if (op != null) entity.setOriginalPrice(op);
			else entity.setOriginalPrice(tax == null ? null : p + tax);
			entity.setTuigaiqian(tuigaiqian);
			entity.setLastSeatInfo(lastSeatInfo);
			return (T) entity;
		}
		return null;
	}

	/**
	 * 构建一个代理实体
	 * 
	 * @param name
	 * @param price
	 * @param originalPrice
	 * @param type
	 * @param clzz
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> T buildAgent(String name, String price, String originalPrice, Integer type, Class<T> clzz) throws Exception {
		Double p = StringUtils.isNotBlank(price) && NumberUtils.isNumber(price) ? Double.valueOf(price.trim()) : null;
		Double op = StringUtils.isNotBlank(originalPrice) && NumberUtils.isNumber(originalPrice) ? Double.valueOf(originalPrice.trim()) : null;
		if (com.foreveross.crawl.domain.airfreight.AgentEntity.class.equals(clzz)) {
			com.foreveross.crawl.domain.airfreight.AgentEntity agent = new com.foreveross.crawl.domain.airfreight.AgentEntity();
			agent.setName(name);
			agent.setPrice(p);
			agent.setOriginalPrice(op);
			agent.setType(type);
			return (T) agent;
		} else if (com.foreveross.crawl.domain.airfreight.doub.ReturnAgentEntity.class.equals(clzz)) {

			com.foreveross.crawl.domain.airfreight.doub.ReturnAgentEntity agent = new com.foreveross.crawl.domain.airfreight.doub.ReturnAgentEntity();
			agent.setAgentName(name);
			agent.setPrice(p);
			agent.setOriginalPrice(op);
			agent.setAgentType(type);
			return (T) agent;
		}
		return null;
	}

	/**
	 * 构建一个代理实体,加入公司，地址
	 * 
	 * @param name
	 * @param price
	 * @param originalPrice
	 * @param type
	 * @param companyName
	 * @param address
	 * @param clzz
	 * @return
	 * @throws Exception
	 */

	public static <T> T buildAgent(String name, String price, String originalPrice, Integer type, String companyName, String address, Class<T> clzz) throws Exception {
		T t = buildAgent(name, price, originalPrice, type, clzz);;
		if (com.foreveross.crawl.domain.airfreight.AgentEntity.class.equals(clzz)) {
			((com.foreveross.crawl.domain.airfreight.AgentEntity) t).setCompanyName(companyName);
			((com.foreveross.crawl.domain.airfreight.AgentEntity) t).setAddress(address);
		} else if (com.foreveross.crawl.domain.airfreight.doub.ReturnAgentEntity.class.equals(clzz)) {
			((com.foreveross.crawl.domain.airfreight.doub.ReturnAgentEntity) t).setCompanyName(companyName);
			((com.foreveross.crawl.domain.airfreight.doub.ReturnAgentEntity) t).setAddress(address);
		}
		return t;
	}

	@SuppressWarnings("unchecked")
	public static <T> T buildTransitEntity(String flightNo, String actuallyFlightNo, String carrierKey, String carrierName, String carrierFullName, String fromAirPort, String fromAirPortName, String toAirPort, String toAirPortName,
			String flightType, Class<T> clzz) throws Exception {
		if (TransitEntity.class.equals(clzz)) {
			return (T) buildTransitEntity(flightNo, actuallyFlightNo, carrierKey, carrierName, carrierFullName, fromAirPort, fromAirPortName, toAirPort, toAirPortName, flightType);
		} else if (ReturnTransitEntity.class.equals(clzz)) {
			return (T) buildReturnTransitEntity(flightNo, actuallyFlightNo, carrierKey, carrierName, carrierFullName, fromAirPort, fromAirPortName, toAirPort, toAirPortName, flightType);
		} else {
			return null;
		}
	}

	public static TransitEntity buildTransitEntity(String flightNo, String actuallyFlightNo, String carrierKey, String carrierName, String carrierFullName, String fromAirPort, String fromAirPortName, String toAirPort, String toAirPortName,
			String flightType) throws Exception {
		TransitEntity t = new TransitEntity();
		t.setFlightNo(flightNo);
		t.setActuallyFlightNo(actuallyFlightNo);
		t.setCarrierKey(carrierKey);
		t.setCarrierName(carrierName);
		t.setCarrierFullName(carrierFullName);
		t.setFromAirPort(fromAirPort);
		t.setFromAirPortName(fromAirPortName);
		t.setToAirPort(toAirPort);
		t.setToAirPortName(toAirPortName);
		t.setFlightType(flightType);
		return t;
	}

	public static ReturnTransitEntity buildReturnTransitEntity(String flightNo, String actuallyFlightNo, String carrierKey, String carrierName, String carrierFullName, String fromAirPort, String fromAirPortName, String toAirPort,
			String toAirPortName, String flightType) throws Exception {
		ReturnTransitEntity t = new ReturnTransitEntity();
		t.setFlightNo(flightNo);
		t.setActuallyFlightNo(actuallyFlightNo);
		t.setCarrierKey(carrierKey);
		t.setCarrierName(carrierName);
		t.setCarrierFullName(carrierFullName);
		t.setFromAirPort(fromAirPort);
		t.setFromAirPortName(fromAirPortName);
		t.setToAirPort(toAirPort);
		t.setToAirPortName(toAirPortName);
		t.setFlightType(flightType);
		return t;
	}

	/**
	 * 生成一个AbstractPlaneInfoEntity，根据是否往返类型决定new的对象 自己去强转
	 * 
	 * @param task
	 * @param carrierKey
	 * @param carrierName
	 * @param carrierFullName
	 * @param startTime
	 * @param endTime
	 * @param flightNo
	 * @param totalLowestPrice
	 * @param agentName
	 * @param totalHighestPrice
	 * @param type
	 * @return
	 */
	public static AbstractPlaneInfoEntity buildPlaneInfo(TaskModel task, String carrierKey, String carrierName, String carrierFullName, String startTime, String endTime, String flightNo, String totalLowestPrice, String agentName,
			String totalHighestPrice, String type) {
		AbstractPlaneInfoEntity entity;

		if (task.getIsReturn() == 0) {// 单程
			entity = new SinglePlaneInfoEntity();
			entity.setFlightDate(task.getFlightDate());
		} else {// 双层
			entity = new DoublePlaneInfoEntity();
			entity.setFlightDate(task.getFlightDate());
			((DoublePlaneInfoEntity) entity).setFlightReturnDate(task.getReturnGrabDate());
		}
		// 去程设置日期
		entity.setStartTime(getFlightTime(task.getFlightDate(), startTime));
		entity.setEndTime(getFlightTime(task.getFlightDate(), endTime));

		setPlaneInfo(task, carrierKey, carrierName, carrierFullName, startTime, endTime, flightNo, totalLowestPrice, agentName, totalHighestPrice, type, entity);
		setPlaneInfo(task, entity, true);
		return entity;
	}

	/**
	 * 获取回程
	 * 
	 * @param task
	 * @param carrierKey
	 * @param carrierName
	 * @param carrierFullName
	 * @param startTime
	 * @param endTime
	 * @param flightNo
	 * @param totalLowestPrice
	 * @param agentName
	 * @param totalHighestPrice
	 * @param type
	 * @return
	 */
	public static ReturnDoublePlaneInfoEntity getReturnTrip(TaskModel task, String carrierKey, String carrierName, String carrierFullName, String startTime, String endTime, String flightNo, String totalLowestPrice, String agentName,
			String totalHighestPrice, String type) {
		ReturnDoublePlaneInfoEntity entity = new ReturnDoublePlaneInfoEntity();
		// 返程设置日期
		entity.setStartTime(getFlightTime(task.getReturnGrabDate(), startTime));
		entity.setEndTime(getFlightTime(task.getReturnGrabDate(), endTime));
		setPlaneInfo(task, carrierKey, carrierName, carrierFullName, startTime, endTime, flightNo, totalLowestPrice, agentName, totalHighestPrice, type, entity);
		setPlaneInfo(task, entity, false);
		return entity;
	}

	public static SinglePlaneInfoEntity getSingleEntity(AbstractPlaneInfoEntity entity) {
		return (SinglePlaneInfoEntity) entity;
	}

	public static ReturnDoublePlaneInfoEntity getReturnDoubleEntity(AbstractPlaneInfoEntity entity) {
		return (ReturnDoublePlaneInfoEntity) entity;
	}

	public static DoublePlaneInfoEntity getDoubleEntity(AbstractPlaneInfoEntity entity) {
		return (DoublePlaneInfoEntity) entity;
	}

	public static void setTransits(AbstractPlaneInfoEntity entity, ArrayList<TransitEntity> transit) {
		if (entity instanceof DoublePlaneInfoEntity) {
			getDoubleEntity(entity).setTransits(transit);
		} else if (entity instanceof SinglePlaneInfoEntity) {
			getSingleEntity(entity).setTransits(transit);
		}
	}

	public static ArrayList getTransits(AbstractPlaneInfoEntity entity) {
		if (entity instanceof DoublePlaneInfoEntity) {
			return getDoubleEntity(entity).getTransits();
		} else if (entity instanceof SinglePlaneInfoEntity) {
			return getSingleEntity(entity).getTransits();
		}
		return null;
	}

	public static void setCabin(AbstractPlaneInfoEntity entity, Set<CabinEntity> cabins) {
		if (entity instanceof DoublePlaneInfoEntity) {
			getDoubleEntity(entity).setCabins(cabins);
		} else if (entity instanceof SinglePlaneInfoEntity) {
			getSingleEntity(entity).setCabins(cabins);
		}
	}

	public static String getDoubleStr(String price) {
		return price.trim().replaceAll(",", "");
	}

	public static String getDoubleStr(Double price) {
		return (price + "").trim().replaceAll(",", "");
	}

	public static Double getDouble(String price) {
		if (StringUtils.isBlank(price)) {
			return null;
		}
		price = price.replaceAll(",", "");
		price = RegHtmlUtil.regStr(price, "[0-9]+\\.{0,1}[0-9]{0,2}", 0);
		return Double.parseDouble(price);
	}

	/**
	 * 设置航班属性
	 * 
	 * @param carrierKey
	 * @param carrierName
	 * @param carrierFullName
	 * @param startTime
	 * @param endTime
	 * @param flightNo
	 * @param totalLowestPrice
	 * @param agentName
	 * @param totalHighestPrice
	 * @param type
	 * @param entity
	 */
	private static void setPlaneInfo(TaskModel task, String carrierKey, String carrierName, String carrierFullName, String startTime, String endTime, String flightNo, String totalLowestPrice, String agentName, String totalHighestPrice, String type,
			AbstractPlaneInfoEntity entity) {
		entity.setCarrierKey(StringUtils.trimEmpty(carrierKey));
		entity.setCarrierName(StringUtils.trimEmpty(carrierName));
		entity.setCarrierFullName(StringUtils.trimEmpty(carrierFullName));

		if (entity.getStartTime() != null && entity.getEndTime() != null) {
			String startStr = DateUtil.formatDay(entity.getStartTime(), "yyyy-MM-dd");
			String endStr = DateUtil.formatDay(entity.getEndTime(), "yyyy-MM-dd");

			// 因为页面获得的数据有时会出现跨天的情况，所以这里加了一个判断，如果结束日期在开始日期之前，则将结束时间加一天
			if (entity.getStartTime() != null && entity.getEndTime() != null && entity.getEndTime().before(entity.getStartTime()) && StringUtils.equals(startStr, endStr)) {
				entity.setEndTime(DateUtils.addDays(entity.getEndTime(), 1));
			}
		}
		entity.setFlightNo(StringUtils.trimEmpty(flightNo));
		entity.setTotalLowestPrice(StringUtils.isNotBlank(totalLowestPrice) && NumberUtils.isNumber(totalLowestPrice) ? Double.valueOf(totalLowestPrice.trim()) : null);
		entity.setTotalHighestPrice(StringUtils.isNotBlank(totalHighestPrice) && NumberUtils.isNumber(totalHighestPrice) ? Double.valueOf(totalHighestPrice.trim()) : null);
		entity.setAgentName(StringUtils.trimEmpty(agentName));
		entity.setFlightType(type);
	}

	private static void setPlaneInfo(TaskModel task, AbstractPlaneInfoEntity entity, boolean isGo) {
		entity.setAreaCode(task.getAreaCode());
		entity.setAreaName(task.getAreaName());

		entity.setGrabChannelName(task.getGrabChannel());
		entity.setGrabChannelId(task.getGrabChannelId());
		if (isGo) {
			entity.setFlightDate(task.getFlightDate());
			entity.setFromCity(task.getFromCity());
			entity.setFromCityName(task.getFromCityName());
			entity.setToCity(task.getToCity());
			entity.setToCityName(task.getToCityName());
		} else {
			entity.setFlightDate(task.getReturnGrabDate());
			entity.setFromCity(task.getToCity());
			entity.setFromCityName(task.getToCityName());
			entity.setToCity(task.getFromCity());
			entity.setToCityName(task.getFromCityName());
		}

		entity.setAttachHbaseKey(task.getAttachHbaseKey());
		if (entity instanceof DoublePlaneInfoEntity) {
			((DoublePlaneInfoEntity) entity).setFlightReturnDate(task.getReturnGrabDate());
		}

	}

	public static ReturnDoublePlaneInfoEntity creatReturnTrip(TaskModel task, String carrierKey, String carrierName, String carrierFullName, String flightNo, String fromAir, String toAir, Date start, Date end, List<ReturnTransitEntity> transit)
			throws Exception {
		ReturnDoublePlaneInfoEntity e = new ReturnDoublePlaneInfoEntity();

		e.setAreaCode(task.getAreaCode());
		e.setFlightDate(task.getFlightDate());
		e.setFromCity(task.getFromCity());
		e.setFromCityName(task.getFromCityName());
		e.setGrabChannelName(task.getGrabChannel());
		e.setGrabChannelId(task.getGrabChannelId());
		e.setToCity(task.getToCity());
		e.setToCityName(task.getToCityName());
		e.setAttachHbaseKey(task.getAttachHbaseKey());
		e.setAreaName(task.getAreaName());

		e.setCarrierKey(carrierKey);
		e.setCarrierName(carrierName);
		e.setCarrierFullName(carrierFullName);
		e.setFlightNo(flightNo);
		e.setFromCity(fromAir);
		e.setToCity(toAir);
		e.setEndTime(CrawlAdapterFactory.getFlightTime(e.getFlightDate(), getSringByDate(end)));
		e.setStartTime(CrawlAdapterFactory.getFlightTime(e.getFlightDate(), getSringByDate(start)));
		// 因为页面获得的数据有时会出现跨天的情况，所以这里加了一个判断，如果结束日期在开始日期之前，则将结束时间加一天
		if (e.getStartTime() != null && e.getEndTime() != null && e.getEndTime().before(e.getStartTime())) {
			e.setEndTime(DateUtils.addDays(e.getEndTime(), 1));
		}
		if (transit.size() > 0) {
			ArrayList<ReturnTransitEntity> set = new ArrayList<ReturnTransitEntity>();
			set.addAll(transit);
			e.setReturnTransits(set);// 中转
		}

		return e;
	}

	// Date 转 String
	private static String getSringByDate(Date dateStr) throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		String queryDates = sdf.format(dateStr);
		return queryDates;
	}

	public static void buildLimitPrice(List<? extends AbstractPlaneInfoEntity> planeInfos) {
		if (planeInfos == null || planeInfos.size() == 0) {
			return;
		}
		//AbstractPlaneInfoEntity first = planeInfos.get(0);

		for (AbstractPlaneInfoEntity absPlaneInfo : planeInfos) {
			if (absPlaneInfo instanceof SinglePlaneInfoEntity) { // 单程
				SinglePlaneInfoEntity planeInfo = getSingleEntity(absPlaneInfo);

				// 价格排序, 如果有税费则按总计排序，没有则按裸价。
				ArrayList<CabinEntity> tempCabin = new ArrayList<CabinEntity>();
				tempCabin.addAll(planeInfo.getCabins());
				orderBySinglePrice(tempCabin);
				CabinEntity low = tempCabin.get(0);
				CabinEntity high = tempCabin.get(tempCabin.size() - 1);
				absPlaneInfo.setTotalLowestPrice(low.getPrice());
				absPlaneInfo.setTotalHighestPrice(high.getPrice());
				absPlaneInfo.setTotalLowestTaxesPrice(low.getTaxesPrice());
				absPlaneInfo.setTotalHighestTaxesPrice(high.getTaxesPrice());
				absPlaneInfo.setSumLowestPrice(low.getOriginalPrice());
				absPlaneInfo.setSumHighestPrice(high.getOriginalPrice());
			} else if (absPlaneInfo instanceof DoublePlaneInfoEntity) { // 往返去程
				DoublePlaneInfoEntity planeInfo = getDoubleEntity(absPlaneInfo);

				ArrayList<CabinRelationEntity> tempCabin = new ArrayList<CabinRelationEntity>();
				tempCabin.addAll(planeInfo.getCabinRelations());
				orderByPrice(tempCabin);
				CabinRelationEntity low = tempCabin.get(0);
				CabinRelationEntity high = tempCabin.get(tempCabin.size() - 1);
				absPlaneInfo.setTotalLowestPrice(low.getFullPrice());
				absPlaneInfo.setTotalHighestPrice(high.getFullPrice());
				absPlaneInfo.setTotalLowestTaxesPrice(low.getTaxesPrice());
				absPlaneInfo.setTotalHighestTaxesPrice(high.getTaxesPrice());
				absPlaneInfo.setSumLowestPrice(low.getTotalFullPrice());
				absPlaneInfo.setSumHighestPrice(high.getTotalFullPrice());

				// 获取去程的舱位最低价格
				ArrayList<CabinEntity> goCabins = new ArrayList<CabinEntity>();
				goCabins.addAll(planeInfo.getCabins());
				orderBySinglePrice(goCabins);
				CabinEntity golow = goCabins.get(0);
				CabinEntity gohigh = goCabins.get(goCabins.size() - 1);
				//舱位无价格，合计价，用relation的记录
				if(!tempCabin.isEmpty() && (!isNullOrZero(tempCabin.get(0).getFullPrice()) || !isNullOrZero(tempCabin.get(0).getTotalFullPrice()))){
						for(ReturnDoublePlaneInfoEntity returnInfo : planeInfo.getReturnPlaneInfos()){
							ArrayList<CabinRelationEntity> relations = new ArrayList<CabinRelationEntity>();
							Set<ReturnCabinEntity> returnCabins = returnInfo.getReturnCabins();
							for(ReturnCabinEntity returnCabin : returnCabins){
									for(CabinRelationEntity relation : tempCabin){
										if(relation.getReturnCabinId().equals(returnCabin.getId())){
											relations.add(relation);
											break;
										}
									}
							}
							if(!relations.isEmpty()){
								orderByPrice(relations);
								 low = relations.get(0);
								 high = relations.get(relations.size() - 1);
								 returnInfo.setTotalLowestPrice(low.getFullPrice());
								 returnInfo.setTotalHighestPrice(high.getFullPrice());
								 returnInfo.setTotalLowestTaxesPrice(low.getTaxesPrice());
								 returnInfo.setTotalHighestTaxesPrice(high.getTaxesPrice());
								 returnInfo.setSumLowestPrice(low.getTotalFullPrice());
								 returnInfo.setSumHighestPrice(high.getTotalFullPrice());
							}
						}
				}else{
					for (ReturnDoublePlaneInfoEntity returnInfo : planeInfo.getReturnPlaneInfos()) {
						ArrayList<ReturnCabinEntity> tempReturnCabin = new ArrayList<ReturnCabinEntity>();
						tempReturnCabin.addAll(returnInfo.getReturnCabins());
						orderByReturnCabinPrice(tempReturnCabin);
						ReturnCabinEntity returnlow = tempReturnCabin.get(0);
						ReturnCabinEntity returnhigh = tempReturnCabin.get(tempReturnCabin.size() - 1);
	
						// // 回程的最低打包价=当前回程航班舱位最低价格加上去程航班仓位最低价
						// returnInfo.setTotalLowestPrice(addDouble(golow.getPrice(), returnlow.getPrice()));
						// returnInfo.setTotalHighestPrice(addDouble(gohigh.getPrice(), returnhigh.getPrice()));
						// returnInfo.setTotalLowestTaxesPrice(addDouble(golow.getTaxesPrice(), returnlow.getTaxesPrice()));
						// returnInfo.setTotalHighestTaxesPrice(addDouble(gohigh.getTaxesPrice(), returnhigh.getTaxesPrice()));
						// returnInfo.setSumLowestPrice(addDouble(golow.getOriginalPrice(), returnlow.getOriginalPrice()));
						// returnInfo.setSumHighestPrice(addDouble(gohigh.getOriginalPrice(), returnhigh.getOriginalPrice()));
	
						 // 回程的最低打包价=当前回程航班舱位最低价格加上去程航班仓位最低价 --- -bright
						 Double reprice = addDouble(golow.getPrice(), returnlow.getPrice());
						 if (reprice != null) returnInfo.setTotalLowestPrice(reprice);
						 reprice = addDouble(gohigh.getPrice(), returnhigh.getPrice());
						 if (reprice != null) returnInfo.setTotalHighestPrice(reprice);
						 reprice = addDouble(golow.getTaxesPrice(), returnlow.getTaxesPrice());
						 if (reprice != null) returnInfo.setTotalLowestTaxesPrice(reprice);
						 reprice = addDouble(gohigh.getTaxesPrice(), returnhigh.getTaxesPrice());
						 if (reprice != null) returnInfo.setTotalHighestTaxesPrice(reprice);
						 reprice = addDouble(golow.getOriginalPrice(), returnlow.getOriginalPrice());
						 if (reprice != null) returnInfo.setSumLowestPrice(reprice);
						 reprice = addDouble(gohigh.getOriginalPrice(), returnhigh.getOriginalPrice());
						 if (reprice != null) returnInfo.setSumHighestPrice(reprice);
					}
				}
			}
		}
	}
	
	private static boolean isNullOrZero(Double d){
		if(d == null || d.doubleValue() == 0){
			return true;
		}
		return false;
	}

	/**
	 * 排序价格
	 * 
	 * @param entitys
	 */
	public static void orderByPrice(List<CabinRelationEntity> entitys) {
		if(entitys != null)
		Collections.sort(entitys, new Comparator<CabinRelationEntity>() {
			@Override
			public int compare(CabinRelationEntity arg0, CabinRelationEntity arg1) {
				Double dt0 = arg0.getTaxesPrice() == null ? arg0.getFullPrice() : addDouble(arg0.getTaxesPrice(), arg0.getFullPrice());
				Double dt1 = arg1.getTaxesPrice() == null ? arg1.getFullPrice() : addDouble(arg1.getTaxesPrice(), arg1.getFullPrice());
				
				Double d0 = dt0 == null ? arg0.getTotalFullPrice() : dt0;
				Double d1 = dt1 == null ? arg1.getTotalFullPrice() : dt1;

				if (d1 == null) {
					return -1;
				}
				if (d0 == null) {
					return 1;
				}
				return d0.compareTo(d1);
			}
		});
	}

	// isTaxes 是否排序税费
	public static void orderBySinglePrice(List<com.foreveross.crawl.domain.airfreight.CabinEntity> entitys) {
		Collections.sort(entitys, new Comparator<com.foreveross.crawl.domain.airfreight.CabinEntity>() {
			@Override
			public int compare(com.foreveross.crawl.domain.airfreight.CabinEntity arg0, com.foreveross.crawl.domain.airfreight.CabinEntity arg1) {
				Double dt0 = arg0.getTaxesPrice() == null ? arg0.getPrice() : addDouble(arg0.getTaxesPrice(), arg0.getPrice());
				Double dt1 = arg1.getTaxesPrice() == null ? arg1.getPrice() : addDouble(arg1.getTaxesPrice(), arg1.getPrice());
				Double d0 = dt0 == null ? arg0.getOriginalPrice() : dt0;
				Double d1 = dt1 == null ? arg1.getOriginalPrice() : dt1;

				if (d1 == null) {
					return -1;
				}
				if (d0 == null) {
					return 1;
				}
				return d0.compareTo(d1);
			}
		});
	}

	// isTaxes 是否排序税费
	public static void orderByReturnCabinPrice(List<ReturnCabinEntity> entitys) {
		Collections.sort(entitys, new Comparator<ReturnCabinEntity>() {
			@Override
			public int compare(ReturnCabinEntity arg0, ReturnCabinEntity arg1) {
				Double dt0 = arg0.getTaxesPrice() == null ? arg0.getPrice() : addDouble(arg0.getTaxesPrice(), arg0.getPrice());
				Double dt1 = arg1.getTaxesPrice() == null ? arg1.getPrice() : addDouble(arg1.getTaxesPrice(), arg1.getPrice());

				Double d0 = dt0 == null ? arg0.getOriginalPrice() : dt0;
				Double d1 = dt1 == null ? arg1.getOriginalPrice() : dt1;

				if (d1 == null) {
					return -1;
				}
				if (d0 == null) {
					return 1;
				}
				return d0.compareTo(d1);
			}
		});
	}

	/**
	 * 得到起飞/gcj dp 时间
	 * <p>
	 * 由flightBatchDate+flightBatchStartTime组合而成
	 * 
	 * @return
	 */
	public static Date getFlightTime(String flightBatchDate, String timez) {
		if (StringUtils.isNotEmpty(flightBatchDate) && StringUtils.isNotEmpty(timez)) {
			// 引处replaceAll(" ", "")替换的不是空格，请不要去掉，后面有处理空格
			timez = timez.trim().replaceAll("^\\W+|\\W+$| ", "");
			String day = "0";// 跨天
			try {
				String time = timez.indexOf(":") > -1 ? timez.replace(":", "") : timez;
				if (time.length() < 4) {
					time = "0" + time;
				}
				if (RegHtmlUtil.regMathcher(time, "[+-]\\d{1,2}?$")) {
					day = RegHtmlUtil.regStr(time, "(.*?)([+-]\\d{1,2}?)$", 2);
					time = RegHtmlUtil.regStr(time, "(.*?)[+-](\\d{1,2}?)$", 1);
				}

				if (time.length() == 3) time = "0" + time;
				else if (time.length() == 2) time = "00" + time;
				else if (time.length() == 1) time = "000" + time;
				Date date;
				if (time.matches("\\w{2,4}?-\\w{1,2}-?.*?")) {
					date = DateUtils.parseDate(time, "yyyy-MM-dd HHmm");
				} else {
					date = DateUtils.parseDate(flightBatchDate + " " + time, "yyyy-MM-dd HHmm");
				}
				if (day.contains("+")) {
					int intday = Integer.parseInt(StringUtils.trim(day.replace("+", "")));
					date = DateUtils.addDays(date, intday);
				} else if (day.contains("-")) {
					int intday = Integer.parseInt(StringUtils.trim(day.replace("-", "")));
					date = DateUtils.addDays(date, -intday);
				}
				return date;
			} catch (java.text.ParseException e) {
				logger.error(e.getMessage());
			}
		}
		return null;
	}

	public static void buildRelation(List<? extends AbstractPlaneInfoEntity> toFlights, List<? extends AbstractPlaneInfoEntity> backFlights) {
		if (toFlights == null || backFlights == null || toFlights.size() == 0 || backFlights.size() == 0) {
			return;
		}

		for (int i = 0; i < toFlights.size(); i++) {

			DoublePlaneInfoEntity toFlight = PlaneInfoEntityBuilder.getDoubleEntity(toFlights.get(i));
			Set<CabinEntity> toCabins = toFlight.getCabins();
			if (toCabins == null || toCabins.size() == 0) {
				continue;
			}
			for (CabinEntity toCabin : toCabins) {
				for (AbstractPlaneInfoEntity absBackFlight : backFlights) {
					ReturnDoublePlaneInfoEntity backFlight = PlaneInfoEntityBuilder.getReturnDoubleEntity(absBackFlight);
					Set<ReturnCabinEntity> backCabins = backFlight.getReturnCabins();
					if (backCabins == null || backCabins.size() == 0) {
						continue;
					}
					for (ReturnCabinEntity backCabin : backCabins) {
						CabinRelationEntity relation = new CabinRelationEntity();
						relation.setPlaneInfoEntity(toFlight);
						relation.setFullPrice(backCabin.getPrice() + toCabin.getPrice());
						relation.setTaxesPrice(addDouble(backCabin.getTaxesPrice(), toCabin.getTaxesPrice()));
						relation.setTotalFullPrice(addDouble(backCabin.getOriginalPrice(), toCabin.getOriginalPrice()));
						relation.setCabinId(toCabin.getId());
						relation.setReturnCabinId(backCabin.getId());
						toFlight.getCabinRelations().add(relation);
					}
				}
			}
			// List<CabinRelationEntity> tempCabinRs = new ArrayList<CabinRelationEntity>();
			// tempCabinRs.addAll(toFlight.getCabinRelations());
			// PlaneInfoEntityBuilder.orderByPrice(tempCabinRs);
			// toFlight.setTotalLowestPrice(tempCabinRs.get(0).getFullPrice());
			// toFlight.setTotalHighestPrice(tempCabinRs.get(tempCabinRs.size()-1).getFullPrice());
		}
	}

	private static Double addDouble(Double d1, Double d2) {
		if (d1 == null && d2 == null) {
			return null;
		}
		return (d1 == null ? 0 : d1) + (d2 == null ? 0 : d2);
	}
	
	/** 获取英文月份。 */
	public static String getEnMonth(String flightDate) {
		String month = RegHtmlUtil.regStr(flightDate, "-(\\d{1,2})-", 1);
		Map<String, String> monthMap = new HashMap<String, String>() {
			private static final long serialVersionUID = 4309679305155800625L;
			{
				put("01", "january");
				put("02", "february");
				put("03", "march");
				put("04", "april");
				put("05", "may");
				put("06", "june");
				put("07", "july");
				put("08", "august");
				put("09", "september");
				put("10", "october");
				put("11", "november");
				put("12", "december");
			}
		};
		return monthMap.get(month);
	}

	// public static DoublePlaneInfoEntity createPlaneInfo(TaskModel task,
	// String carrierKey, String carrierName, String carrierFullName, Date startTime,
	// Date endTime, String flightNo, String lowerPrice,
	// String agentName, String highPrice, String type,
	// List<TransitEntity> transit,Set<com.foreveross.crawl.domain.airfreight.CabinEntity> cabins,Set<ReturnDoublePlaneInfoEntity> returnTirps) throws Exception {
	// DoublePlaneInfoEntity entity=new DoublePlaneInfoEntity();
	//
	// entity.setAreaCode(task.getAreaCode());
	// entity.setFlightDate (task.getFlightDate());
	// entity.setFromCity( task.getFromCity());
	// entity.setFromCityName(task.getFromCityName());
	// entity.setGrabChannelName(task.getGrabChannel());
	// entity.setGrabChannelId(task.getGrabChannelId());
	// entity.setToCity(task.getToCity());
	// entity.setToCityName(task.getToCityName());
	// entity.setAttachHbaseKey(task.getAttachHbaseKey());
	// entity.setAreaName(task.getAreaName());
	//
	// entity.setCarrierKey(StringUtils.trimEmpty(carrierKey));
	// entity.setCarrierName(StringUtils.trimEmpty(carrierName));
	// entity.setCarrierFullName(StringUtils.trimEmpty(carrierFullName));
	//
	// entity.setEndTime(CrawlAdapterFactory.getFlightTime(entity.getFlightDate(), getSringByDate(endTime)));
	// entity.setStartTime(CrawlAdapterFactory.getFlightTime(entity.getFlightDate(), getSringByDate(startTime)));
	// //因为页面获得的数据有时会出现跨天的情况，所以这里加了一个判断，如果结束日期在开始日期之前，则将结束时间加一天
	// if(entity.getStartTime()!=null &&
	// entity.getEndTime()!=null && entity.getEndTime().before(entity.getStartTime())){
	// entity.setEndTime(DateUtils.addDays(entity.getEndTime(), 1));
	// }
	//
	// if(transit.size()>0){
	// Set<TransitEntity> transitSet=new HashSet<TransitEntity>();
	// transitSet.addAll(transit);
	// entity.setTransits(transitSet);
	// }
	//
	// entity.setFlightNo(StringUtils.trimEmpty(flightNo));
	// entity.setTotalHighestPrice(Double.parseDouble(highPrice));
	// entity.setTotalLowestPrice(Double.parseDouble(lowerPrice));j
	// entity.setFlightType(type);
	// entity.setCabins(cabins);
	// entity.setReturnPlaneInfos(returnTirps);//返程
	//
	// return entity;
	//
	//
	// }
	//

	public static void main(String[] args) {
		//System.out.println(addDouble(2d, 8.6d));
		System.out.println(getFlightTime("2014-10-06", "01:00+1天"));
	}
}
